const messageListeners = [];
const openListeners = [];
const errorListeners = [];
const closeListeners = [];
const validateListeners = [];
const chat = {
    getDomain: function () {
        return process.env.IM_API_URL;
    },
    getApiUrl: function (method) {
        return this.getDomain() + "api/v1/" + method;
    },
    init: function (token) {
        this.user = {};
        this.token = token;
        this.validate();
    },
    my: function () {
        return this.user;
    },
    agent: function () {
        return this.agentInfo;
    },
    cs: function () {
        if ('robot' === this.cva.lastCs.customerType.value) return null;
        return this.cva.lastCs;
    },
    setCs: function (cs) {
        if (this.cva) {
            this.cva.lastCs = cs;
        }
    },
    validate: function () {
        let _self = this;
        this.ajax_post_json_request({
            method: 'validate',
            token: this.token
        }, (json) => {
            if (json.status) {
                _self.user = {
                    userId: json.data.userId,
                    userName: json.data.name,
                    userLogo: json.data.logo,
                    agentId: json.data.agentId,
                    onlineStatus: json.data.status.value,
                    customer: 'message' === json.data.customerType.value || 'order' === json.data.customerType.value
                };
                _self.agentInfo = json.agent;
                _self.agentInfo.robot = json.robot;
                _self.server = json.wss;
                _self.cva = json.cva;
                if (_self.user.customer || _self.cs()) {
                    _self.doConnect();
                }
                if (json.token && json.token.authkey && json.token.sessionid) {
                    localStorage.setItem("authkey", json.token.authkey);
                    localStorage.setItem("sessionid", json.token.sessionid);
                }
            } else {
                _self.callbackError(json);
            }
            _self.validateCallback(json);
        }, function (err) {
            _self.callbackError({
                message: "无法与服务器通信，请查检网络！"
            });
        });
    },
    doConnect: function () {
        let _self = this;
        if (!_self.ws) {
            this.connect();
            _self.timer = setInterval(function () {
                if (_self.ws) {
                    _self.ws.send("0");
                    if (3 === parseInt(_self.ws.readyState)) {
                        console.warn("checking status :" + _self.ws.readyState);
                        _self.connect();
                    }
                } else {
                    _self.connect();
                }
            }, 25000);
        }
    },
    connect: function () {
        if ('WebSocket' in window) {
            this.ws = new WebSocket(this.server + "?token=" + encodeURIComponent(this.token));
        } else if ('MozWebSocket' in window) {
            this.ws = new MozWebSocket(this.server + "?token=" + encodeURIComponent(this.token));
        }
        this.ws.addEventListener("open", this.socketOpen);
        this.ws.addEventListener("message", this.socketMessage);
        this.ws.addEventListener("close", this.socketClose);
    },
    close: function () {
        if (this.ws) {
            clearInterval(this.timer);
            this.ws.close();
        }
        this.ws = null;
    },
    socketOpen: function (event) {
        for (let i = 0; i < openListeners.length; i++) {
            openListeners[i](event);
        }
    },

    socketMessage: function (event) {
        if (event.data !== '1') {
            for (let i = 0; i < messageListeners.length; i++) {
                messageListeners[i](event);
            }
        }
    },

    callbackError: function (data) {
        console.error(data);
        for (let i = 0; i < errorListeners.length; i++) {
            errorListeners[i](data);
        }
    },

    socketClose: function (event) {
        console.error(event);
        for (let i = 0; i < closeListeners.length; i++) {
            closeListeners[i](event);
        }
        clearInterval(this.timer);
    },
    validateCallback: function (json) {
        for (let i = 0; i < validateListeners.length; i++) {
            validateListeners[i](json);
        }
    },
    addMessageListener: function (listener) {
        messageListeners.push(listener);
    },

    addSocketOpenListener: function (listener) {
        openListeners.push(listener);
    },

    addErrorListener: function (listener) {
        errorListeners.push(listener);
    },

    addSocketCloseListener: function (listener) {
        closeListeners.push(listener);
    },
    addValidateListener: function (listener) {
        validateListeners.push(listener);
    },
    sendMessage: function (content, toId, type, event, cvaId) {
        if (this.ws && 1 === parseInt(this.ws.readyState)) {
            let msg = {
                content: content,
                from: this.userId,
                to: toId,
                agentId: this.agentId,
                type: type,
                event: event,
                cvaId: cvaId ? cvaId : this.cva.cvaId,
                id: 0
            };
            console.log(msg);
            this.ws.send(JSON.stringify(msg));
        } else {
            this.callbackError({message: "会话已中止！"});
        }
    },
    formatDate: function (timstamp, fmt = 'yyyy-MM-dd hh:mm:ss') {
        let date = new Date();
        date.setTime(parseInt(timstamp) * 1000);
        if (/(y+)/.test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
        }
        let o = {
            'M+': date.getMonth() + 1,
            'd+': date.getDate(),
            'h+': date.getHours(),
            'm+': date.getMinutes(),
            's+': date.getSeconds()
        };
        for (let k in o) {
            if (new RegExp(`(${k})`).test(fmt)) {
                let str = o[k] + '';
                fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : this.padLeftZero(str));
            }
        }
        return fmt;
    },
    padLeftZero: function (str) {
        return ('00' + str).substr(str.length);
    },
    knowledges: function (keyword, page, limit, callback) {
        this.ajax_post_json_request({
            method: 'knowledges',
            agentId: this.my().agentId,
            page: page,
            keyword: keyword,
            limit: limit,
            token: this.token
        }, callback);
    },
    history: function (to, page, limit, lastMsgId, keyword, callback) {
        this.ajax_post_json_request({
            method: 'historyUserMessages',
            from: this.my().userId,
            targetUserId: to,
            lastMsgId: lastMsgId ? lastMsgId : 0,
            keyword: keyword || '',
            page: page,
            limit: limit,
            token: this.token
        }, callback);
    },
    chatToRobot: function (message, callback) {
        this.ajax_post_json_request({
            method: 'chatToRobot2',
            cvaId: this.cva.cvaId,
            message: message,
            type: 'desktop',
            token: this.token
        }, callback);
    },
    connectToHuman: function (callback) {
        this.ajax_post_json_request({
            method: 'toHuman',
            token: this.token
        }, (json) => {
            if (json.status) {
                this.server = json.data.wss;
                this.cva = json.data.cva;
                this.doConnect();
            } else if (407 === json.code) {
                this.doConnect();
            }
            if (callback) callback(json);
        });
    },
    takeCustomer: function (targetUserId, callback) {
        this.ajax_post_json_request({
            method: 'takeCustomer',
            targetUserId: targetUserId,
            token: this.token
        }, callback)
    },
    takeWaitingCustomers: function (callback) {
        this.ajax_post_json_request({
            method: 'takeWaitingCustomers',
            token: this.token
        }, callback);
    },
    historyUsers: function (page, limit, callback) {
        this.ajax_post_json_request({
            method: 'historyUsers',
            customerServiceId: this.my().userId,
            page: page,
            limit: limit,
            token: this.token
        }, callback);
    },
    /**
     * 主动关闭会话
     * @param cvaId 会话ID
     * @param callback
     */
    closeCva: function (cvaId, callback) {
        this.ajax_post_json_request({
            method: 'closeCva',
            cvaId: cvaId ? cvaId : this.cva.cvaId,
            token: this.token
        }, (json) => {
            this.close();
            if (callback) callback(json);
        });
    },
    /**
     * 转接
     * @param cvaId 会话ID
     * @param csId 转接客服ID
     * @param callback
     */
    transferCva: function (cvaId, csId, callback) {
        this.ajax_post_json_request({
            method: 'transferCva',
            cvaId: cvaId,
            csId: csId,
            token: this.token
        }, callback)
    },
    /**
     * 会话小结
     * @param cvaId
     * @param review
     * @param callback
     */
    reviewCva: function (cvaId, review, callback) {
        this.ajax_post_json_request({
            method: 'reviewCva',
            cvaId: cvaId,
            review: review,
            token: this.token
        }, callback)
    },
    /**
     * 会话评分
     * @param cvaId 会话ID
     * @param resolved 是否解决
     * @param score 评分，默认传0
     * @param userComment 用户文字评价
     * @param callback
     */
    scoreCva: function (cvaId, resolved, score, userComment, callback) {
        this.ajax_post_json_request({
            method: 'scoreCva',
            cvaId: cvaId ? cvaId : this.cva.cvaId,
            resolved: resolved,
            score: score,
            userComment: userComment,
            token: this.token
        }, callback)
    },
    /**
     * 获取在线客服
     * @param callback
     */
    onlineCs: function (callback) {
        this.ajax_post_json_request({
            method: 'onlineCs',
            token: this.token
        }, callback)
    },
    /**
     * 改变客服在线状态
     * @param status in ['online','busy','offline']
     * @param callback
     */
    csOnlineStatus: function (status, callback) {
        this.ajax_post_json_request({
            method: 'csOnlineStatus',
            status: status,
            token: this.token
        }, callback)
    },
    ajax_post_json_request: function (data, success_function_handle, error_function_handle) {
        this.post(this.getApiUrl(data.method), data, success_function_handle, error_function_handle);
    },
    post: function (url, data, success_function_handle, error_function_handle) {
        let xhr = new XMLHttpRequest();
        let formData = new FormData();
        for (let key in data) {
            formData.append(key, data[key]);
        }
        formData.append("version", "1.0");
        xhr.open("post", url);
        xhr.send(formData);
        xhr.onreadystatechange = function () {
            if (xhr.status === 200) {
                if (xhr.readyState === 4) {
                    let responseData = JSON.parse(xhr.responseText);
                    if (success_function_handle) success_function_handle(responseData);
                }
            } else {
                if (error_function_handle) {
                    let responseData = JSON.parse(xhr.responseText);
                    if (error_function_handle) error_function_handle(responseData);
                } else {
                    alert("网络通信异常！" + xhr.responseText);
                }
            }
        };
    },
    messageConvert: function (serverMsg) {
        return {
            id: serverMsg.id,
            from: serverMsg.from,
            fromUser: serverMsg.fromUser,
            to: serverMsg.to ? serverMsg.to : chat.my().userId,
            toUser: serverMsg.toUser ? serverMsg.toUser : chat.my(),
            content: serverMsg.content,
            type: serverMsg.type,
            event: serverMsg.event,
            timestamp: chat.formatDate(serverMsg.timestamp, "yyyy-MM-dd hh:mm:ss")
        };
    }
};
Array.prototype.contains = function (obj) {
    let len = this.length;
    while (len--) {
        if (this[len] === obj) {
            return true
        }
    }
    return false;
};
Object.isNullOrUndefined = function (obj) {
    return typeof (obj) === "undefined" || obj == null
        || obj.toString().length === 0;
};
export default chat;

